home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / x11 / games / xboing2.4.patch < prev    next >
Text File  |  1997-08-26  |  15KB  |  546 lines

  1. Hello Xboing fans,
  2.  
  3. This is a patch for version 2.4 of XBoing. A cool bloke called Alexander
  4. sent me this patch which helps to fix the game speed problem. His email is
  5. below followed by the patch. Just cut the patch code out and apply this
  6. to the source for xboing2.4
  7.  
  8. Good luck.
  9.  
  10. PS: Don't forget to cut off my sig at the end of the patch!
  11.  
  12. email message from Alexander :-
  13.  
  14. I guess as a result of some confusion, SleepSync() invokes usleep()
  15. with the parameter of milliseconds, while BSD usleep() implemented in
  16. all the OS I am aware of requires microseconds. Moreover, the
  17. internally generated usleep() accepts milliseconds in one compilation
  18. instance and microseconds in another.
  19.  
  20. Xboing 2.3 didn't sleep at all (except for the "SLOW_SPEED" game
  21. mode), so the frame rate was totally defined by the processor power
  22. while the variation of game speed was induced by the ball velocity
  23. changing in accordance with the "speedLevel".
  24.  
  25. There is some improvement in Xboing 2.4. Now the SleepSync()
  26. accumulates the required sleeping time up until it exceeds 33.33 ms.
  27. For the default warp factor (5) it results in 6 frames being passed
  28. without delay followed by the invocation of usleep( 35 ) after the
  29. 7th.
  30.  
  31. As no OS is capable to put a process asleep for a few microseconds due
  32. to the overheads involved in context switching, Linux (and I suspect
  33. the other OS too) uses a threshold resolution - the process is
  34. suspended until the next tick of the PSU timer, something like 20 or
  35. 16.66 ms.
  36.  
  37. So somehow it works due to combination of bugs and the current
  38. technology limitations. However, no influence on the frame rate was
  39. achieved, the sleeping time does not depend on the parameter of
  40. usleep() (as long as it remains relatively small) but it depends on
  41. the phase of internal frame progress. This can result in a significant
  42. drop in the game speed if the processor is not fast enough meaning
  43. that 7 frames can not be processed within the timer resolution (16.66
  44. ms). Correcting this bug won't help: If you replaced usleep( 35 ) by
  45. usleep( 35*1000 ) the game would be ridiculously slow.
  46.  
  47. As it seems to me, the adequate solution is to synchronise the frame
  48. progress with the real time, i.e. to stabilise the frame rate at a
  49. particular level regardless of the processor power. The traces of such
  50. an attempt can be found in SleepSync(): the time taken by XSynch is
  51. taken out of the sleeping time.
  52.  
  53. In the patch attached to this letter, SleepSync() is replaced by a
  54. simple FLL/PLL timer stabilising the frame rate according to its "ms"
  55. parameter (so it is 5ms/frame as a default). Because the both, the
  56. frame rate and the ball velocity are involved, I reduced the range of
  57. "userDelay" (see patch for "main.c"). Maybe it requires further
  58. reduction. Also the timings in "bonus.c" and "presents.c" were
  59. adjusted. Due to the real-time frame rates, they can now be calculated
  60. much more precisely.
  61.  
  62. Regards,
  63. ---
  64. Alex Bolychevsky                      | voice: +44-1483-259000 x 2384
  65. Dept of Electronic & Electrical Eng., | fax: +44-1483-34139
  66. University of Surrey,                 | telex: 859331 UNIVSY G
  67. Guildford, GU2 5XH, United Kingdom    | e-mail: a.bolychevsky@ee.surrey.ac.uk
  68.  
  69. ------------------------ >8 ---- CUT HERE ---- 8< --------------------------
  70. diff -u --recursive xboing/bonus.c xbpatch/bonus.c
  71. --- xboing/bonus.c    Fri Nov 22 01:28:46 1996
  72. +++ xbpatch/bonus.c    Tue Jan 14 18:48:28 1997
  73. @@ -311,7 +311,7 @@
  74.      XFlush(display);
  75.  
  76.      SetBonusWait(BONUS_SCORE, frame + 5);
  77. -    SetGameSpeed(SLOW_SPEED);
  78. +    SetGameSpeed(MEDIUM_SPEED);
  79.  
  80.      DEBUG("set bonus mode to BONUS_SCORE.")
  81.  }
  82. @@ -326,7 +326,7 @@
  83.  {
  84.      DEBUG("in function DoScore() in bonus.c")
  85.  
  86. -    SetGameSpeed(SLOW_SPEED);
  87. +    SetGameSpeed(MEDIUM_SPEED);
  88.  
  89.      /* Nice message rewarding you for your efforts */
  90.      strcpy(string, "Congratulations on finishing this level.");
  91. @@ -336,7 +336,7 @@
  92.  
  93.      ypos += (35 + GAP);
  94.      SetBonusWait(BONUS_BONUS, frame + LINE_DELAY);
  95. -    SetGameSpeed(SLOW_SPEED);
  96. +    SetGameSpeed(MEDIUM_SPEED);
  97.      DEBUG("set bonus mode to BONUS_BONUS.")
  98.  }
  99.  
  100. @@ -363,7 +363,7 @@
  101.          DrawShadowCentredText(display, window, textFont, 
  102.              string, ypos, blue, TOTAL_WIDTH);
  103.  
  104. -        SetGameSpeed(SLOW_SPEED);
  105. +        SetGameSpeed(MEDIUM_SPEED);
  106.  
  107.          /* Now skip to the next sequence */
  108.          SetBonusWait(BONUS_LEVEL, frame + LINE_DELAY);
  109. @@ -387,7 +387,7 @@
  110.              DrawShadowCentredText(display, window, textFont, 
  111.                  string, ypos, blue, TOTAL_WIDTH);
  112.  
  113. -            SetGameSpeed(SLOW_SPEED);
  114. +            SetGameSpeed(MEDIUM_SPEED);
  115.  
  116.              /* Now skip to the next sequence */
  117.              SetBonusWait(BONUS_LEVEL, frame + LINE_DELAY);
  118. @@ -411,7 +411,7 @@
  119.              bonusScore += ComputeScore(SUPER_BONUS_SCORE);
  120.              DisplayScore(display, scoreWindow, bonusScore);
  121.      
  122. -            SetGameSpeed(SLOW_SPEED);
  123. +            SetGameSpeed(MEDIUM_SPEED);
  124.  
  125.              /* Now skip to the next sequence */
  126.              SetBonusWait(BONUS_LEVEL, frame + LINE_DELAY);
  127. @@ -454,7 +454,7 @@
  128.          ypos += (int) (textFont->ascent + GAP * 1.5);
  129.          firstTime = True;
  130.  
  131. -        SetGameSpeed(SLOW_SPEED);
  132. +        SetGameSpeed(MEDIUM_SPEED);
  133.      }
  134.  }
  135.  
  136. @@ -468,7 +468,7 @@
  137.  {
  138.      int secs, theLevel;
  139.  
  140. -    SetGameSpeed(SLOW_SPEED);
  141. +    SetGameSpeed(MEDIUM_SPEED);
  142.  
  143.      /* Get the number of seconds left on the clock */
  144.      secs = GetLevelTimeBonus();
  145. @@ -533,7 +533,7 @@
  146.              /* Play the sound for the super bonus */
  147.              if (noSound == False) playSoundFile("Doh3", 80);
  148.              
  149. -            SetGameSpeed(SLOW_SPEED);
  150. +            SetGameSpeed(MEDIUM_SPEED);
  151.  
  152.              /* Get ready for the next sequence */
  153.              SetBonusWait(BONUS_TIME, frame + LINE_DELAY);
  154. @@ -569,7 +569,7 @@
  155.          SetBonusWait(BONUS_TIME, frame + LINE_DELAY);
  156.          ypos += (textFont->ascent + GAP/2);
  157.          firstTime = True;
  158. -        SetGameSpeed(SLOW_SPEED);
  159. +        SetGameSpeed(MEDIUM_SPEED);
  160.      }
  161.  }
  162.  
  163. @@ -583,7 +583,7 @@
  164.  {
  165.      int secs = 0;
  166.  
  167. -    SetGameSpeed(SLOW_SPEED);
  168. +    SetGameSpeed(MEDIUM_SPEED);
  169.  
  170.      /* Get the number of seconds left on the clock */
  171.      secs = GetLevelTimeBonus();
  172. @@ -627,7 +627,7 @@
  173.      int myrank = 0;
  174.      char str[5];
  175.  
  176. -    SetGameSpeed(SLOW_SPEED);
  177. +    SetGameSpeed(MEDIUM_SPEED);
  178.  
  179.      /* Obtain current ranking for this score */
  180.      myrank = GetHighScoreRanking(score);
  181. @@ -680,7 +680,7 @@
  182.  {
  183.      DEBUG("DoEndText in bonus screen.")
  184.  
  185. -    SetGameSpeed(SLOW_SPEED);
  186. +    SetGameSpeed(MEDIUM_SPEED);
  187.  
  188.      /* Finishing sentence - so you know what level to do */
  189.      sprintf(string, "Prepare for level %ld", level+1);
  190. diff -u --recursive xboing/main.c xbpatch/main.c
  191. --- xboing/main.c    Fri Nov 22 01:28:46 1996
  192. +++ xbpatch/main.c    Tue Jan 14 18:32:30 1997
  193. @@ -156,7 +156,7 @@
  194.  
  195.      /* Set an entire game speedup or slowdown speed */
  196.      temp = (speed / (long) userDelay);
  197. -    userDelay = delay;
  198. +    userDelay = delay/2 + 3;
  199.      speed = (long) (temp * userDelay);
  200.      speedLevel = 10 - delay;
  201.  }
  202. diff -u --recursive xboing/misc.c xbpatch/misc.c
  203. --- xboing/misc.c    Fri Nov 22 01:28:46 1996
  204. +++ xbpatch/misc.c    Tue Jan 14 18:54:45 1997
  205. @@ -89,8 +89,8 @@
  206.  #ifdef SYSV
  207.  #ifdef __clipper__
  208.      struct timeval tv;
  209. -    tv.tv_sec=((usec)/1000);
  210. -    tv.tv_usec=(((usec)%1000)*1000);
  211. +    tv.tv_sec=((usec)/1000000);
  212. +    tv.tv_usec=((usec)%1000000);
  213.      select(1,NULL,NULL,NULL,&tv);
  214.  #else
  215.      poll((struct poll *) 0, (size_t) 0, usec / 1000);   /* ms resolution */
  216. @@ -105,6 +105,68 @@
  217.  #endif
  218.  
  219.  #if NeedFunctionPrototypes
  220. +static    int    kudelay(unsigned long count)
  221. +#else
  222. +static    int    kudelay(count)
  223. +unsigned long count;
  224. +#endif
  225. +{
  226. +    unsigned int    bluff = 1;
  227. +
  228. +    while( count-- != 0 )    /* this can hardly be "optimised out" */
  229. +    bluff = (bluff ^ ((bluff & 1) * 0x6110)) >> 1;
  230. +
  231. +    return( bluff );
  232. +}
  233. +
  234. +#if NeedFunctionPrototypes
  235. +static    void kusleep(unsigned long usec)
  236. +#else
  237. +static    void kusleep(usec)
  238. +        unsigned long usec;
  239. +#endif
  240. +{
  241. +    static float    kuliber_time = 0.0;
  242. +    static float    kuliber_count = 0.0;
  243. +    static unsigned long    kutimerswap = (1000000 / 15);
  244. +    struct timeval    st, et;
  245. +    long        gap;
  246. +    unsigned long    count;
  247. +
  248. +    if( kuliber_time == 0.0 )
  249. +    {
  250. +    count = 0x1000;        /* calibrate delay loop */
  251. +    gettimeofday(&st, NULL);
  252. +
  253. +    while( True )
  254. +    {
  255. +        kudelay( count );
  256. +        count = (count << 1);
  257. +        gettimeofday(&et, NULL);
  258. +        gap = (((et.tv_sec - st.tv_sec) * 1000000) +
  259. +            (et.tv_usec - st.tv_usec) );
  260. +
  261. +        if( gap > 400*1000 )
  262. +        break;
  263. +    }
  264. +
  265. +    kuliber_time = (float)(gap/4);
  266. +    kuliber_count = (float)(((count-1)&~0xFFF)>>2);
  267. +    }
  268. +
  269. +    if( usec > kutimerswap )
  270. +    {
  271. +    kutimerswap = (1000000 / 30);
  272. +    usleep( usec );        /* using usleep() for low resolution only */
  273. +    }
  274. +    else
  275. +    {
  276. +    kutimerswap = (1000000 / 15);
  277. +    kudelay( (unsigned long)(kuliber_count*((float)usec/kuliber_time)) );
  278. +    }
  279. +}
  280. +
  281. +#if NeedFunctionPrototypes
  282.  void sleepSync(Display *display, unsigned long ms)
  283.  #else
  284.  void sleepSync(display, ms)
  285. @@ -112,27 +174,85 @@
  286.      unsigned long ms;
  287.  #endif
  288.  {
  289. -    struct timeval st, et;
  290. -    long SyncTime;
  291. -    static unsigned long accu;
  292. +    static long        Expected_time = 0;
  293. +    static long        Ref_sec = 0;
  294. +    static long        Ref_usec = 0;
  295. +    static long        Sleeping_time = 0;
  296. +    static int        PLL_filter = 0;
  297. +    struct timeval    st;
  298. +    long        elapsed;
  299. +    long        dodelay;
  300. +    float        x;
  301.  
  302. -    gettimeofday(&st, NULL);
  303.      XSync(display, False);
  304. -    gettimeofday(&et, NULL);
  305.  
  306. -    SyncTime = (((et.tv_sec - st.tv_sec) * 1000) +
  307. -               ((et.tv_usec - st.tv_usec) / 1000) );
  308. +    gettimeofday(&st, NULL);
  309. +
  310. +    if( Ref_sec == 0 )
  311. +    {
  312. +    Ref_sec = st.tv_sec;    /* take the initial reference point */
  313. +    Ref_usec = st.tv_usec;
  314. +    Sleeping_time = ms * 1000;
  315. +    }
  316. +
  317. +    elapsed = (st.tv_sec - Ref_sec) * 1000000 + (st.tv_usec - Ref_usec);
  318. +    dodelay = Sleeping_time;
  319. +
  320. +    if( PLL_filter > 0 && elapsed != 0 )    /* Phase lock loop */
  321. +    {
  322. +    dodelay = Expected_time + Sleeping_time - elapsed;
  323. +
  324. +    if( dodelay < 0 )
  325. +    {
  326. +        dodelay = 0; PLL_filter--;
  327. +    }
  328. +    else
  329. +        if( dodelay > 2*Sleeping_time )
  330. +        {
  331. +        dodelay = 2*Sleeping_time; PLL_filter--;
  332. +        }
  333. +        else
  334. +        PLL_filter = 3;
  335. +
  336. +    if( elapsed > 40*Sleeping_time && Expected_time > 40*Sleeping_time )
  337. +    {
  338. +        elapsed -= 20*Sleeping_time; /* Ref. point shouldn't be far away*/
  339. +        Expected_time -= 20*Sleeping_time;
  340. +        Ref_usec += 20*Sleeping_time;
  341. +        Ref_sec += Ref_usec/1000000; Ref_usec %= 1000000;
  342. +    }
  343. +    }
  344.  
  345. -/*    if ((ms) > ((1000 / 60) + SyncTime))
  346. -        usleep(ms - SyncTime);
  347. -*/
  348. -    if ((ms + accu) > ((1000 / 30) + SyncTime)) 
  349. +    if( PLL_filter <= 0 && elapsed > 40000 )    /* Frequency lock loop */
  350.      {
  351. -        usleep(ms +accu - SyncTime);
  352. -        accu = 0;
  353. +    /* feedback filter */
  354. +    x = 0.5 + 0.5 * (float)Expected_time / (float)elapsed;
  355. +
  356. +    if( x < 0.966 )    /* Acceleration must be strongly limited */
  357. +        x = 0.966;
  358. +
  359. +    if( x > 2.0 )
  360. +        x = 2.0;
  361. +
  362. +    Sleeping_time = (long)((float)Sleeping_time * x);
  363. +
  364. +    if( Sleeping_time < 500 )
  365. +        Sleeping_time = 500;
  366. +
  367. +    if( x > 0.99 && x < 1.01 && Sleeping_time > ms*500 )
  368. +        PLL_filter = -1 - 4*PLL_filter; /* locked - it's time to try PLL */
  369. +    else
  370. +        PLL_filter = 0;
  371. +
  372. +    Ref_sec = st.tv_sec;
  373. +    Ref_usec = st.tv_usec;
  374. +    Expected_time = 0;
  375. +    dodelay = Sleeping_time;
  376.      }
  377. -    else if (ms > SyncTime)
  378. -       accu += (ms - SyncTime);
  379. +
  380. +    kusleep( dodelay );
  381. +
  382. +    Expected_time += ms * 1000;
  383.  }
  384.  
  385.  #if NeedFunctionPrototypes
  386. diff -u --recursive xboing/presents.c xbpatch/presents.c
  387. --- xboing/presents.c    Fri Nov 22 01:28:46 1996
  388. +++ xbpatch/presents.c    Tue Jan 14 18:35:40 1997
  389. @@ -287,7 +287,7 @@
  390.      }
  391.  #endif
  392.  
  393. -    SetPresentWait(PRESENT_TEXT1, frame + 800);
  394. +    SetPresentWait(PRESENT_TEXT1, frame + 200);
  395.  }
  396.  
  397.  #if NeedFunctionPrototypes
  398. @@ -309,7 +309,7 @@
  399.      RenderShape(display, window, justin, justinM,
  400.          x, y, 285, 44, True);
  401.  
  402. -    SetPresentWait(PRESENT_TEXT2, frame + 300);
  403. +    SetPresentWait(PRESENT_TEXT2, frame + 100);
  404.  }
  405.  
  406.  #if NeedFunctionPrototypes
  407. @@ -331,7 +331,7 @@
  408.      RenderShape(display, window, kibell, kibellM,
  409.          x, y, 260, 40, True);
  410.  
  411. -    SetPresentWait(PRESENT_TEXT3, frame + 500);
  412. +    SetPresentWait(PRESENT_TEXT3, frame + 200);
  413.  }
  414.  
  415.  #if NeedFunctionPrototypes
  416. @@ -355,7 +355,7 @@
  417.      RenderShape(display, window, presents, presentsM,
  418.          x, y, 410, 44, True);
  419.  
  420. -    SetPresentWait(PRESENT_TEXT_CLEAR, frame + 750);
  421. +    SetPresentWait(PRESENT_TEXT_CLEAR, frame + 250);
  422.  }
  423.  
  424.  #if NeedFunctionPrototypes
  425. @@ -375,7 +375,7 @@
  426.  
  427.      FadeAwayArea(display, window, x, y, 410, 44);
  428.  
  429. -    SetPresentWait(PRESENT_LETTERS, frame + 10);
  430. +    SetPresentWait(PRESENT_LETTERS, frame + 5);
  431.  }
  432.  
  433.  /* The distances for the gap inbetwen blocks */
  434. @@ -404,7 +404,7 @@
  435.          DrawLetter(display, window, i, x, y);
  436.          x += 10 + dists[i];
  437.  
  438. -        SetPresentWait(PRESENT_LETTERS, frame + 300);
  439. +        SetPresentWait(PRESENT_LETTERS, frame + 100);
  440.      }
  441.      else
  442.      {
  443. @@ -416,7 +416,7 @@
  444.          x += dists[3];
  445.          DrawLetter(display, window, 3, x, y);
  446.  
  447. -        SetPresentWait(PRESENT_SHINE, frame + 200);
  448. +        SetPresentWait(PRESENT_SHINE, frame + 100);
  449.      }
  450.  
  451.      i++;
  452. @@ -463,7 +463,7 @@
  453.          if (in == 11)
  454.          {
  455.              XCopyArea(display, store, window, gc, 0, 0, 20, 20, x, y);
  456. -            SetPresentWait(PRESENT_SPECIAL_TEXT1, frame + 500);
  457. +            SetPresentWait(PRESENT_SPECIAL_TEXT1, frame + 100);
  458.          }
  459.      }
  460.  }
  461. @@ -499,7 +499,7 @@
  462.          len = strlen(wisdom);
  463.          x = ((PLAY_WIDTH + MAIN_WIDTH) / 2) - 
  464.              (XTextWidth(dataFont, wisdom, len) / 2);
  465. -        nextFrame = frame + 10;
  466. +        nextFrame = frame + 5;
  467.          first = False;
  468.      }
  469.  
  470. @@ -508,11 +508,11 @@
  471.          if (noSound == False) playSoundFile("key", 60);
  472.          DrawText(display, window, x, y, dataFont, red, wisdom, i);
  473.  
  474. -        nextFrame = frame + 30;
  475. +        nextFrame = frame + 15;
  476.  
  477.          i++;
  478.          if (i > len)
  479. -            SetPresentWait(PRESENT_SPECIAL_TEXT2, frame + 700);
  480. +            SetPresentWait(PRESENT_SPECIAL_TEXT2, frame + 150);
  481.      }
  482.  }
  483.  
  484. @@ -542,7 +542,7 @@
  485.          len = strlen(wisdom2);
  486.          x = ((PLAY_WIDTH + MAIN_WIDTH) / 2) - 
  487.              (XTextWidth(dataFont, wisdom2, len) / 2);
  488. -        nextFrame = frame + 10;
  489. +        nextFrame = frame + 5;
  490.          first = False;
  491.      }
  492.  
  493. @@ -551,11 +551,11 @@
  494.          if (noSound == False) playSoundFile("key", 60);
  495.          DrawText(display, window, x, y, dataFont, red, wisdom2, i);
  496.  
  497. -        nextFrame = frame + 30;
  498. +        nextFrame = frame + 15;
  499.  
  500.          i++;
  501.          if (i > len)
  502. -            SetPresentWait(PRESENT_SPECIAL_TEXT3, frame + 700);
  503. +            SetPresentWait(PRESENT_SPECIAL_TEXT3, frame + 150);
  504.      }
  505.  }
  506.  
  507. @@ -584,7 +584,7 @@
  508.          len = strlen(wisdom3);
  509.          x = ((PLAY_WIDTH + MAIN_WIDTH) / 2) - 
  510.              (XTextWidth(dataFont, wisdom3, len) / 2);
  511. -        nextFrame = frame + 10;
  512. +        nextFrame = frame + 5;
  513.          first = False;
  514.      }
  515.  
  516. @@ -593,11 +593,11 @@
  517.          if (noSound == False) playSoundFile("key", 60);
  518.          DrawText(display, window, x, y, dataFont, red, wisdom3, i);
  519.  
  520. -        nextFrame = frame + 30;
  521. +        nextFrame = frame + 15;
  522.  
  523.          i++;
  524.          if (i > len)
  525. -            SetPresentWait(PRESENT_CLEAR, frame + 800);
  526. +            SetPresentWait(PRESENT_CLEAR, frame + 200);
  527.      }
  528.  }
  529.  
  530. @@ -642,7 +642,7 @@
  531.          yb -= 10;
  532.  
  533.          if (yt > ((PLAY_HEIGHT + MAIN_HEIGHT) / 2))
  534. -            SetPresentWait(PRESENT_FINISH, frame + 20);
  535. +            SetPresentWait(PRESENT_FINISH, frame + 10);
  536.  
  537.          nextFrame = frame + 20;
  538.      }
  539.  
  540. ------------------------ >8 ---- CUT HERE ---- 8< --------------------------
  541.  
  542. Cheers
  543.  
  544. Justin Kibell - UNIX Administrator   - RMIT Comm. Eng. - rcojk@co.rmit.edu.au
  545. Ph: 9282 2456 - System Administrator - RMIT C.A.T.T.   - jck@catt.rmit.edu.au
  546.